<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="./d3.v5.min.js"></script>
  <style>
    #tooltip {
      position: absolute;
      width: 100px;
      height: 100px;
      background: white;
      display: none;
    }
  </style>
</head>

<body>

  <div id="app">
  </div>
  <div id="tooltip"></div>

  <hr>
  <button id="btn_add">add</button>
  <button id="btn_update">update</button>

  <script>

    const chart_width = 600;
    const chart_height = 450;
    const padding = 25;
    var sort_flag = false;

    //数据
    var dataset = [];
    var container = d3.select("#app");

    //创建画布
    var svg = container.append('svg')
      .attr('width', chart_width)
      .attr('height', chart_height)
      .style('background', '#efefef');


    //生成随机数据
    function createData() {
      for (let i = 0; i < 5; i++) {
        let num = Math.ceil(Math.random() * 400)
        dataset.push(num);
      }
    }
    createData();

    //序数比例尺
    var x_scale = d3.scaleBand()
      .domain(d3.range(dataset.length))
      .range([padding, chart_width - padding * 2])
      .paddingInner(0.05)

    //线性比例尺
    var y_scale = d3.scaleLinear()
      .domain([0, d3.max(dataset)])
      .range([padding, chart_height - padding * 2])


    //添加柱形
    function addRect() {
      svg.selectAll('rect')
        .data(dataset)
        .enter()
        .append('rect');

      svg.selectAll('rect')
        .data(dataset)
        .attr('width', x_scale.bandwidth())
        .attr('height', function (d, i) {
          return y_scale(d);
        })
        .attr('fill', 'green')
        .attr('x', function (d, i) {
          return x_scale(i);
        })
        .attr('y', function (d, i) {
          return chart_height - y_scale(d);
        }).on('mouseover', function (d, i) {
          d3.select(this).style('fill', 'orange')
          let top = chart_height - y_scale(d);
          let left = x_scale(i);
          d3.select('#tooltip')
            .text(d)
            .style('display', 'block')
            .style('left', left + 'px')
            .style('top', top + 'px');
        })
        .on('mouseout', function () {
          d3.select(this).style('fill', 'green')
          d3.select('#tooltip')
            .style('display', 'none')
        })
        .on('click', () => {
          sort();
        })
    }

    //排序
    function sort() {
      d3.selectAll('rect').sort(function (a, b) {
        return sort_flag ? d3.descending(a, b) : d3.ascending(a, b);
      })
        .transition()
        .duration(500)
        .attr('x', function (d, i) {
          return x_scale(i);
        })
        .attr('y', function (d, i) {
          return chart_height - y_scale(d);
        })


      d3.selectAll('text').sort(function (a, b) {
        return sort_flag ? d3.descending(a, b) : d3.ascending(a, b);
      })
        .transition()
        .duration(500)
        .attr('x', function (d, i) {
          return x_scale(i) + x_scale.bandwidth() / 2;
        })
        .attr('y', function (d, i) {
          return chart_height - y_scale(d);
        })

      sort_flag = !sort_flag;
    }

    //添加文本数据
    function addText() {
      svg.selectAll('text')
        .data(dataset)
        .enter()
        .append('text')
        .text(function (d) {
          return d;
        })

      svg.selectAll('text')
        .data(dataset)
        .attr('x', function (d, i) {
          return x_scale(i) + x_scale.bandwidth() / 2;
        })
        .attr('y', function (d, i) {
          return chart_height - y_scale(d);
        })
        .attr('text-anchor', 'middle')
    }

    //更新比例尺
    function updateScale() {
      x_scale.domain(d3.range(dataset.length));
      y_scale.domain([0, d3.max(dataset)]);
    }

    d3.select('#btn_add').on('click', () => {
      let num = Math.ceil(Math.random() * 400)
      dataset.push(num);
      updateScale();
      addRect();
      addText();
    })

    d3.select('#btn_update').on('click', function () {
      dataset = [45, 300, 200, 139, 380, 288, 333];
      updateScale();
      addRect();
      addText();
    })

    addRect();
    addText();
  </script>

</body>

</html>